#include "front/text_normalize.h"

using namespace std;
using namespace ppspeech;

const map<string, string> mcMapWebsiteTable = {
	{":",	"colon"},
	{"&",	"and"},
	{"/",	"slash"},
	{".",	"dot"},
	{"?",	"question mark"},
	{"@",	"at"},
	{"#",	"hash"},
	{"%",	"percent"},
	{"-",	"dash"},
	{"_",	"underscore"},
	{"=",	"equals"},
};

const vector<string> VecStr_EnglishMonth = {
	"january",	"february",		"march",		"april",	"may",			"june",
	"july",		"august",		"september",	"october",	"november",		"december"
};


string TextNormalizer::ReplaceMethod(const vector<string>& fpInVecItems, RepleceMethodEnum fcInRepleceMethod)
{
	string tStrReplace = "";
	switch (fcInRepleceMethod)
	{
		//------------------
		case RME_zh_colon_ratio:
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += "比";
				}
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[i],  true,false,  false, false);
			}
			break;

		case RME_en_colon_ratio:
			tStrReplace += " ";
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += " to ";
				}
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[i] );
			}
			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_colon_dianfenmiao:
			{
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[0],  true,false,  true,false);
				tStrReplace += "点";

				string tStrMinute = TnZh_NumNegDec2Int(fpInVecItems[1],  true,false,  false,false);
				tStrReplace += (tStrMinute.length() == 3) ? "零" : "";
				tStrReplace += (tStrMinute == "一") ? "壹" : tStrMinute;
				tStrReplace += "分";

				string tStrSecond = TnZh_NumNegDec2Int(fpInVecItems[2],  true,false,  false,false);
				tStrReplace += (tStrSecond.length() == 3) ? "零" : "";
				tStrReplace += (tStrSecond == "一") ? "壹" : tStrSecond;
				tStrReplace += "秒";
			}
			break;

		case RME_en_colon_dianfenmiao:
			tStrReplace += " ";

			if( stoi(fpInVecItems[1]) == 0 ) {	//分为00
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[0] );	//时
				tStrReplace += " o'clock";
			}
			else {
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[0] );	//时
				tStrReplace += " ";
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[1] );	//分
			}

			if( stoi(fpInVecItems[2]) > 0 ) {	//秒大于0
				tStrReplace += " and ";
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[2] );	//秒
				tStrReplace += " second";
			}

			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_colon_dianfen:
			tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[0],  true,false,  true,false);
			tStrReplace += "点";

			if(fpInVecItems[1] == "00") {
				tStrReplace += "整";
			}
			else {
				string tStrMinute = TnZh_NumNegDec2Int(fpInVecItems[1],  true,false,  false,false);
				tStrReplace += (tStrMinute.length() == 3) ? "零" : "";
				tStrReplace += tStrMinute;
				tStrReplace += "分";
			}
			break;

		case RME_en_colon_dianfen:
			tStrReplace += " ";
			if( fpInVecItems.size() <= 1 || stoi(fpInVecItems[1]) == 0 ) {	//分为00
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[0] );		//时
				tStrReplace += " o'clock";
			}
			else {
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[0] );		//时
				tStrReplace += " ";
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[1] );		//分
			}
			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_chinesedate:
			if(fpInVecItems.size() > 0 && fpInVecItems[0] != "") {
				tStrReplace += TnZh_EachDigit2Str(fpInVecItems[0], false);
				tStrReplace += "年";
			}
			if(fpInVecItems.size() > 1 && fpInVecItems[1] != "") {
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[1],  true,false,  false,false);
				tStrReplace += "月";
			}
			if(fpInVecItems.size() > 2 && fpInVecItems[2] != "") {
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[2],  true,false,  false,false);

				if(fpInVecItems.size() > 3 && fpInVecItems[3] != "") {
					tStrReplace += fpInVecItems[3];
				}
				else {
					tStrReplace += "日";
				}
			}
			break;

		case RME_en_chinesedate:
			tStrReplace += " ";
			if(fpInVecItems.size() > 1 && fpInVecItems[1] != "") {
				const int tMonth = stoi(fpInVecItems[1]);
				if(tMonth > 0 && tMonth <= 12) {	//有效月份
					tStrReplace += VecStr_EnglishMonth.at(tMonth-1);
				}
				else {	//避免报错
					tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[1] );
				}
				tStrReplace += ",";
			}
			if(fpInVecItems.size() > 2 && fpInVecItems[2] != "") {
				const int tDay = stoi(fpInVecItems[2]);
				if(tDay > 0) {						//有效日期
					tStrReplace += TnEn_OrdinalNum2English(tDay);
				}
				else {	//避免报错
					tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[2] );
				}
				tStrReplace += ",";
			}
			if(fpInVecItems.size() > 0 && fpInVecItems[0] != "") {
				tStrReplace += ReplaceMethod(vector<string>{fpInVecItems[0]}, RME_en_year);
				tStrReplace += " ";
			}
			tStrReplace += " ";
			break;

		case RME_en_year:
			if(fpInVecItems.size() == 1) {
				const int tYear = stoi(fpInVecItems[0]);
				if(tYear >= 1000  &&  tYear <= 9999  &&  tYear % 100 >= 10) {		//四位数
					tStrReplace += TnEn_NumNegDec2Int( to_string(tYear / 100) );
					tStrReplace += " ";
					tStrReplace += TnEn_NumNegDec2Int( to_string(tYear % 100) );
				}
				else {
					tStrReplace += TnEn_NumNegDec2Int( to_string(tYear) );
				}
			}
			break;

		//------------------
		case RME_zh_subtraction:
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += "减";
				}
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[i],  true,false,  false,false);
			}
			break;

		case RME_en_subtraction:
			tStrReplace += " ";
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += " minus ";
				}
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[i] );
			}
			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_telephone:
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += "，";
				}
				tStrReplace += TnZh_EachDigit2Str(fpInVecItems[i], true);
			}
			break;

		case RME_en_telephone:
			tStrReplace += " ";
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += ",";
				}
				tStrReplace += TnEn_EachDigit2Str(fpInVecItems[i]);
			}
			tStrReplace += " ";
			break;
		//------------------
		case RME_zh_range:
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += "到";
				}
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[i],  true,false,  false,true);
			}
			break;

		case RME_en_range:
			tStrReplace += " ";
			for(int i=0; i<fpInVecItems.size(); i++) {
				if(i > 0)  {
					tStrReplace += " to ";
				}
				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[i] );
			}
			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_letter_number:
			for(size_t i=0; i<fpInVecItems.size(); i++) {
				string tStrLetNum = fpInVecItems[i];
				transform(tStrLetNum.begin(), tStrLetNum.end(), tStrLetNum.begin(), ::toupper);

				tStrReplace += " ";
				tStrReplace += TnZh_EachDigit2Str(fpInVecItems[i], false);
				tStrReplace += " ";
			}
			break;

		case RME_en_letter_number:
			for(size_t i=0; i<fpInVecItems.size(); i++) {
				string tStrLetNum = fpInVecItems[i];
				transform(tStrLetNum.begin(), tStrLetNum.end(), tStrLetNum.begin(), ::toupper);

				tStrReplace += " ";
				tStrReplace += TnEn_EachDigit2Str(fpInVecItems[i]);
				tStrReplace += " ";
			}
			break;

		//------------------
		case RME_zh_integer_1yix_2liang3_yi1:		//1读yix，2读liang3，其他带1读yi1
			if(fpInVecItems.size() == 1) {
				if(fpInVecItems[0]=="1") {
					tStrReplace += "一";
				}
				else {
					tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[0],  true,false,  true,true);
				}
			}
			break;
		
		case RME_zh_integer_yi1_liang3:		//1读yi1，2读liang3
			if(fpInVecItems.size() == 1) {
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[0],  true,false,  true,true);
			}
			break;

		//------------------
		case RME_zh_fraction:			//中文的分数
			if(fpInVecItems.size() == 2) {
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[1],  true,false,  false,false);
				tStrReplace += " 分之 ";
				tStrReplace += TnZh_NumNegDec2Int(fpInVecItems[0],  true,false,  false,false);
			}
			break;

		case RME_en_fraction:			//英文的分数
			if(fpInVecItems.size() == 2) {
				tStrReplace += " ";
				
				const int tFenzi = stoi(fpInVecItems[0]);
				const int tFenmu = stoi(fpInVecItems[1]);

				tStrReplace += TnEn_NumNegDec2Int( fpInVecItems[0] );	//分子
				tStrReplace += " ";
				tStrReplace += TnEn_OrdinalNum2English( tFenmu );		//分母
				if(tFenzi > 1) {
					tStrReplace += "'s";
				}

				tStrReplace += " ";
			}
			break;

		//------------------
		case RME_zh_negative_decimal:			//中文的，负数&小数
			tStrReplace += " ";
			for(const string tcVecItem : fpInVecItems) {
				tStrReplace += TnZh_NumNegDec2Int(tcVecItem,  true,false,  false,false);
				tStrReplace += " ";
			}
			break;
		
		case RME_en_negative_decimal:			//英文的，负数&小数
			tStrReplace += " ";
			for(const string tcVecItem : fpInVecItems) {
				tStrReplace += TnEn_NumNegDec2Int(tcVecItem);
				tStrReplace += " ";
			}
			break;

		case RME_en_ordinal_number:				//英文的序数词
			tStrReplace += " ";
			for(const string tcVecItem : fpInVecItems) {
				tStrReplace += TnEn_OrdinalNum2English( (long)std::stoi(tcVecItem) );
				tStrReplace += " ";
			}
			break;

		//------------------
		case RME_zh_percent:			//百分数
			if(fpInVecItems.size() == 1) {
				string tPercent = fpInVecItems[0];
				if(tPercent[tPercent.length()-1] == '%') {
					tPercent = tPercent.substr(0, tPercent.length()-1);
				}
				tStrReplace += "百分之";
				tStrReplace += TnZh_NumNegDec2Int(tPercent,  true,false,  false,false);
			}
			break;

		case RME_en_percent:			//百分数
			tStrReplace += " ";
			if(fpInVecItems.size() == 1) {
				string tPercent = fpInVecItems[0];
				if(tPercent[tPercent.length()-1] == '%') {
					tPercent = tPercent.substr(0, tPercent.length()-1);
				}

				tStrReplace += TnEn_NumNegDec2Int(tPercent);
				tStrReplace += " percent";
			}
			tStrReplace += " ";
			break;

		//------------------
		case RME_zh_digit_yi1:
			for(size_t i=0; i<fpInVecItems.size(); i++) {
				//字符拆分
				tStrReplace += TnZh_EachDigit2Str(fpInVecItems[i], false);
			}
			break;

		case RME_digit_yao:
			for(size_t i=0; i<fpInVecItems.size(); i++) {
				//字符拆分
				tStrReplace += TnZh_EachDigit2Str(fpInVecItems[i], true);
			}
			break;

		//------------------
		case RME_en_website:
			for(string tStrChar : fpInVecItems) {
				const auto tFindPos = mcMapWebsiteTable.find(tStrChar);
				if(tFindPos != mcMapWebsiteTable.end()) {
					tStrReplace += " ";
					tStrReplace += tFindPos->second;
					tStrReplace += " ";
				}
				else {
					const char tChar = tStrChar[0];
					if(tChar >= '0' && tChar <= '9') {
						tStrReplace += " ";
						tStrReplace += mcVecNumberYi1.at( tChar-'0' );
						tStrReplace += " ";
					}
					else {
						tStrReplace += tStrChar;
					}
				}
			}
			break;

		default:
			break;
	}
	return tStrReplace;
}

int TextNormalizer::FindPatternCount(const string& fpInSentence, const string& fpInPattern)
{
	int tCount = 0;
	size_t tStart = 0;
	size_t tEnd = 0;
	while(tStart < fpInSentence.length()) {
		tEnd = fpInSentence.find(fpInPattern, tStart);
		if(string::npos == tEnd) {
			return tCount;
		}
		tCount++;
		tStart = tEnd + fpInPattern.length();
	}
	return tCount;
}


size_t TextNormalizer::FindVectorPatternCount(const vector<wstring>& fpInVecWords, const vector<string>& fpInVecPatterns, const enum LanguageEnum fcInLanguage)
{
	wstring tWstrCombine = L"";
	for(const wstring tcWord : fpInVecWords) {
		tWstrCombine += tcWord;
		if(fcInLanguage == LANG_EN) {
			tWstrCombine += L" ";
		}
	}
	string tStrSentence = wstring2utf8string(tWstrCombine);
	transform(tStrSentence.begin(), tStrSentence.end(), tStrSentence.begin(), ::tolower);	//大写转小写

	int tCount = 0;
	for(const string tcPattern : fpInVecPatterns) {
		tCount += FindPatternCount(tStrSentence, tcPattern);
	}
	return tCount;
}

